package com.Nuyoah.demo01.service.serviceImpl;

import cn.dev33.satoken.stp.StpUtil;
import com.Nuyoah.demo01.DTO.RoleBindDTO;
import com.Nuyoah.demo01.DTO.UserDTO;
import com.Nuyoah.demo01.DTO.UserLoginDTO;
import com.Nuyoah.demo01.DTO.UserPageQry;
import com.Nuyoah.demo01.Exceptions.AlreadyExistEmail;
import com.Nuyoah.demo01.Exceptions.UnBanErrorException;
import com.Nuyoah.demo01.VO.UserVO;
import com.Nuyoah.demo01.common.JsonResult;
import com.Nuyoah.demo01.entity.User;
import com.Nuyoah.demo01.mappers.UserMapper;
import com.Nuyoah.demo01.service.CaptchaService;
import com.Nuyoah.demo01.service.MailService;
import com.Nuyoah.demo01.service.UserService;
import com.Nuyoah.demo01.utils.BCryptUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;


import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.pagehelper.PageHelper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * UserService的实现类，提供用户相关操作的具体实现
 */
@Service
@Slf4j
public class UserServiceImpl implements UserService {

    /**
     * 自动注入UserMapper，用于执行用户相关的数据库操作
     */
    @Resource
    private UserMapper userMapper;
    @Resource
    private CaptchaService captchaService;
    @Autowired
    MailService service;
    @Value("${spring.mail.username}")
    private String from;


    /**
     * 根据用户名获取用户信息
     *
     * @param username 用户名
     * @return 用户对象，如果未找到则返回null
     */
    @Override
    public User getUserByName(String username) {
        return userMapper.getUserByName(username);
    }

    /**
     * 插入新用户到数据库
     *
     *  待插入的用户对象
     * @return 影响的行数，大于0表示成功
     */
//    @Override
//    public Integer insertUser(User user) {
//        //在service层进行加密
//        user.setPassword(BCryptUtil.enCrypt(user.getPassword()));
//        user.setCreatedAt(LocalDateTime.now());
//        user.setUpdatedAt(LocalDateTime.now());
//        return userMapper.insertUser(user);
//
//    }

    public JsonResult insertUser(Map<String, Object> requestBody) {
        try {
            User user = new User();
            user.setUsername((String) requestBody.get("username"));
            user.setEmail((String) requestBody.get("email"));
            user.setPassword(BCryptUtil.enCrypt((String) requestBody.get("password")));
            user.setCreatedAt(LocalDateTime.now());
            user.setUpdatedAt(LocalDateTime.now());

            String captcha = (String) requestBody.get("captcha");
            String sessionId = (String) requestBody.get("sessionId");

            if (!captchaService.validateCaptcha(captcha, sessionId)) {
                return new JsonResult<>("1", "验证码错误");
            }

            Integer result = userMapper.insertUser(user);
            if (result > 0) {
                log.info("用户注册成功，用户ID：{}", user.getUserId());
//                注册成功之后进行邮件发送，会导致响应延时，需要考虑使用优化方案，可考虑使用异步、aop等处理方式
                service.sendmail(from, user.getEmail(),
                        "注册成功通知", "恭喜你成为SC社区的一员！");
                return new JsonResult<>("200", "用户注册成功");
            } else {
                return new JsonResult<>("1", "用户注册失败");
            }
        } catch (DataIntegrityViolationException e) {
            return new JsonResult<>("1", "用户名已存在或者邮箱已被注册");
        } catch (Exception e) {
            e.printStackTrace();
            return new JsonResult<>("1", "服务器错误");
        }
    }

    /**
     * 验证用户登录
     *
     * @param userLoginDTO 包含用户名和密码的用户对象
     * @return 如果找到匹配的用户则返回true，否则返回false
     */

    /*public boolean login(UserLoginDTO userLoginDTO, String sessionId) {
//        User foundUser = userMapper.getUserByUsernameAndPassword(userLoginDTO.getUsername(), userLoginDTO.getPassword());
//        return foundUser != null;

        //修改为使用BCrypt进行密码验证
        String hashed = userMapper.getPasswordByUsername(userLoginDTO.getUsername());
        return BCryptUtil.deCrypt(userLoginDTO.getPassword(), hashed);
    }*/

    public JsonResult login(UserLoginDTO userLoginDTO) {

        //在数据库中查询userLoginDTO.getUsername()对应的user_id
        User user = this.getUserByName(userLoginDTO.getUsername());
//        if (user == null) {
//            return new JsonResult<>("1", "用户名不存在");
//        }
//        if (!BCryptUtil.deCrypt(userLoginDTO.getPassword(),user.getPassword())) {
//            return new JsonResult<>("1", "密码错误");
//        }
        if (user.getUserId() == null) {
            return new JsonResult<>("1", "用户不存在");
        }
        if (user.getStatus() == 1) {
            return new JsonResult<>("1", "用户已被封禁");
        }

        // 获取前端传递的 sessionId
        String sessionId = userLoginDTO.getSessionId();
        if (!captchaService.validateCaptcha(userLoginDTO.getCaptcha(),sessionId)) {
            return new JsonResult<>("1", "验证码错误");
        }

        //使用BCrypt进行密码验证
        String hashed = userMapper.getPasswordByUsername(userLoginDTO.getUsername());
        boolean deCrypt = BCryptUtil.deCrypt(userLoginDTO.getPassword(), hashed);
        if (deCrypt) {
            // 使用Sa-Token生成Token
            StpUtil.login(user.getUserId());
            String token = StpUtil.getTokenValue();
            return new JsonResult<>("200", "登录成功");
        } else {
            return new JsonResult<>("1", "用户名或密码错误");
        }
    }


    /**
     * 更新用户信息
     */
    /*@Override
    public Integer updateUser(User user) {
        //先加密再插入
        String password = BCryptUtil.enCrypt(user.getPassword());
        user.setPassword(password);
        user.setUpdatedAt(LocalDateTime.now());
        return userMapper.updateUser(user);
    }*/
    public JsonResult updateUser(Integer id, String username, String password, String email) {


        // 检查email是否已经存在
        User existingUser = getUserByEmail(email);
        if (existingUser != null && !existingUser.getUserId().equals(id)) {
//            return new JsonResult<>("1", "该邮箱已被其他用户使用");
            throw new AlreadyExistEmail("该邮箱已被其他用户使用");
        }
        User user = new User();
        user.setUserId(id);
        user.setUsername(username);
        user.setEmail(email);
        user.setPassword(password);
        //先加密再插入
        String pw = BCryptUtil.enCrypt(user.getPassword());
        user.setPassword(pw);
        user.setUpdatedAt(LocalDateTime.now());

        Integer result = userMapper.updateUser(user);
        if (result > 0) {
            return new JsonResult<>("200", "用户更新成功");
        } else {
            return new JsonResult<>("1", "用户更新失败");
        }

    }

    /**
     * 删除用户
     *
     * @param user_id 用户ID
     * @return
     */
    @Override
    public JsonResult deleteUser(Integer user_id) {
        //影响的结果数，大于0表示成功
        Integer result = userMapper.deleteUser(user_id);
//        if (result > 0) {
            return new JsonResult<>("200", "用户删除成功");
//        } else {

//        }
    }

    /**
     * 封禁用户
     *
     * @param user_id 用户ID
     */
    @Override
    public JsonResult banUser(Integer user_id) {
        //影响的结果数，大于0表示成功
        Integer result = userMapper.banUser(user_id);
        if (result > 0) {
            return new JsonResult<>("200", "用户已封禁");
        } else {
            return new JsonResult<>("1", "封禁失败");
        }

    }

    /**
     * 解封用户
     *
     * @param user_id 用户ID
     */
    public JsonResult unbanUser(Integer user_id) {
//        return userMapper.unbanUser(user_id);
        //影响的结果数，大于0表示成功
        Integer result = userMapper.unbanUser(user_id);
        if (result > 0) {
            return new JsonResult<>("200", "用户已解封");
        } else {
            throw new UnBanErrorException("解封失败");
        }
    }

    /**
     * 根据邮箱获取用户信息
     *
     * @param email 用户邮箱
     * @return 用户对象，如果未找到则返回null
     */
    @Override
    public User getUserByEmail(String email) {
        return userMapper.getUserByEmail(email);
    }

    /**
     * 查询全部用户信息
     *
     * @return 用户列表，包含所有用户的基本信息
     */
    @Override
//    public List<UserDTO> selectAllUsers() {
//        List<User> userList = userMapper.selectAllUsers();
//        List<UserDTO> userDTOList = new ArrayList<>();
//        for (User user : userList) {
//            UserDTO userDTO = new UserDTO();
//            userDTO.setUsername(user.getUsername());
//            userDTO.setUserId(user.getUserId());
//            userDTOList.add(userDTO);
//        }
//        return userDTOList;
//    }

    public JsonResult selectAllUsers() {
        try {
            List<User> userList = userMapper.selectAllUsers();
            List<UserDTO> userDTOList = new ArrayList<>();
            for (User user : userList) {
                UserDTO userDTO = new UserDTO();
                userDTO.setUsername(user.getUsername());
                userDTO.setUserId(user.getUserId());
                userDTOList.add(userDTO);
            }
            return new JsonResult<>(userDTOList, "获取成功");
        } catch (Exception e) {
            // 捕获异常，返回错误信息
            e.printStackTrace(); // 打印异常堆栈信息，便于调试
            return new JsonResult<>("1", "获取失败：" + e.getMessage());
        }
    }

    /**
     * 分页查询用户
     * @return 用户列表
     */
    @Override
    public List<UserDTO> selectPageUsers(UserPageQry qry) {
        PageHelper.startPage(qry.getPageNum(),qry.getPageSize());
        List<User> userList = userMapper.selectPageUsers(qry);
        List<UserDTO> userDTOList = new ArrayList<>();
        for (User user : userList) {
            UserDTO userDTO = new UserDTO();
            userDTO.setUsername(user.getUsername());
            userDTO.setUserId(user.getUserId());
            userDTOList.add(userDTO);
            userDTO.setEmail(user.getEmail());
            userDTO.setStatus(user.getStatus());
            userDTO.setCreatedAt(user.getCreatedAt());
            userDTO.setUpdateAt(user.getUpdatedAt());
        }
        return userDTOList;
    }

    /**
     * 分页查询，使用IPage
     * @return 用户列表
     */
    @Override
    public IPage<UserDTO> selectPage(UserPageQry qry) {
        Page<UserDTO> page = new Page<>(qry.getPageNum(), qry.getPageSize());
        QueryWrapper<UserDTO> queryWrapper = new QueryWrapper<>();
        queryWrapper.like(StringUtils.isNotBlank(qry.getUsername()), "username", qry.getUsername())
                .like(StringUtils.isNotBlank(qry.getEmail()), "email", qry.getEmail());
                return userMapper.selectPage(page, queryWrapper);
    }

    @Override
    public String generateCaptcha() {
        return captchaService.generateCaptcha().toString();
    }

    @Override
    public boolean validateCaptcha(String userInput, String sessionId) {
        return captchaService.validateCaptcha(userInput,sessionId);
    }

    @Override
    public UserVO getUserById(Integer userId) {
        return userMapper.getUserById(userId);
    }

    public JsonResult setAdmin(Integer id) {
        try {
//            检查目标用户是否为管理员
            int count = userMapper.isAdmin(id) != null ? 1 : 0;
            if (count == 1) {
                return new JsonResult<>("1", "该用户已拥有此身份");
            }
            Integer result = userMapper.setAdmin(id);
            if (result > 0) {
                return new JsonResult<>("0", "设置成功");
            } else {
                return new JsonResult<>("1", "设置失败");
            }
        } catch (Exception e) {
            e.printStackTrace();
            return new JsonResult<>("1", "设置失败：" + e.getMessage());
        }
    }

    @Override
    public JsonResult<String> bindRole(RoleBindDTO roleBindDTO) {
        String userId = roleBindDTO.getUserId();
        String roleId = roleBindDTO.getRoleId();
        Integer count = userMapper.getRoleById(userId, roleId);
        if (count == 1) {
            return new JsonResult<>("1", "该用户已拥有此身份");
        }else {
            Integer result = userMapper.bindRole(roleBindDTO);
            if (result > 0) {
                return new JsonResult<>("0", "绑定成功");
            } else {
                return new JsonResult<>("1", "绑定失败");
            }
        }
    }
    public JsonResult<String> assignRole(Integer roleId, Integer permId) {
        Integer result = userMapper.assignRole(roleId, permId);
        if (result > 0) {
            return new JsonResult<>("0", "赋权成功");
        }else {
            return new JsonResult<>("1", "赋权失败");
        }
    }
}
